package com.rogers.monster.web.project;

import java.util.*;


import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.ActionListener;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;

import com.icesoft.faces.component.inputfile.FileInfo;
import com.icesoft.faces.component.inputfile.InputFile;
import com.icesoft.faces.component.selectinputtext.SelectInputText;
import com.rogers.monster.service.ProjectService;
import com.rogers.monster.util.InputFileData;
import com.rogers.monster.vo.CAProfile;
import com.rogers.monster.vo.Project;
import com.rogers.monster.vo.Reporting_person;
/**
 * @author paul.ning
 * 
 */
public class ProjectSearch {

	private ProjectService projectService;
	private ProjectSearchCriteria psc = new ProjectSearchCriteria();
	private List<Project> projectList = new ArrayList<Project>();
	private List<Reporting_person> vpFullList = new ArrayList<Reporting_person>();
	private List<Reporting_person> vpMatched = new ArrayList<Reporting_person>();
	@SuppressWarnings("unused")
	private boolean hasResult = false;
	private String selectedId;
	private Project selectedProject;
    private int selectedCAIndex;
    private CAProfile selectedCA;
	private boolean showCAInfo = false;
	


	// File sizes used to generate formatted label
    public static final long MEGABYTE_LENGTH_BYTES = 1048000l;
    public static final long KILOBYTE_LENGTH_BYTES = 1024l;

    // files associated with the current user
    private final List fileList =  Collections.synchronizedList(new ArrayList());
    // latest file uploaded by client
    private InputFileData currentFile;
    // file upload completed percent (Progress)
    private int fileProgress;

    private boolean autoUpload = true;
	
	
	
	
	
	public String getSelectedId() {
		return selectedId;
	}

	public void setSelectedId(String selectedId) {
		this.selectedId = selectedId;
	}

	public ProjectSearchCriteria getPsc() {
		return psc;
	}

	public void setPsc(ProjectSearchCriteria psc) {
		this.psc = psc;
	}

	public void searchProject(ActionEvent e) {
		projectList = projectService.getListOfProjects(psc);
	}

	public ProjectService getProjectService() {
		return projectService;
	}

	public void setProjectService(ProjectService projectService) {
		this.projectService = projectService;
	}

	public List<Project> getProjectList() {
		return projectList;
	}

	public void setProjectList(List<Project> projectList) {
		this.projectList = projectList;
	}

	public boolean getHasResult() {
		return !projectList.isEmpty();
	}

	public void setHasResult(boolean hasResult) {
		this.hasResult = !projectList.isEmpty();
	}

	public void showVpList(ValueChangeEvent event) {

		if (event.getComponent() instanceof SelectInputText) {

			// get the number of displayable records from the component
			SelectInputText autoComplete = (SelectInputText) event
					.getComponent();
			// get the new value typed by component user.
			String newWord = (String) event.getNewValue();

			vpMatched = generatePersonListMatches(newWord, 15);

			// if there is a selected item then find the city object of the
			// same name
			if (autoComplete.getSelectedItem() != null) {
				psc.setVp_name(autoComplete.getSelectedItem().getValue()
						.toString());
				// fire effect to draw attention
				// valueChangeEffect.setFired(false);
			}
			// if there was no selection we still want to see if a proper
			// city was typed and update our selectedCity instance.
			else {
				Reporting_person tmp = getFindPersonMatch(newWord);
				if (tmp != null) {
					psc.setVp_name(tmp.getFirst_name());
					// fire effect to draw attention
					// valueChangeEffect.setFired(false);
				}
			}

		}
	}

	private Reporting_person getFindPersonMatch(String personName) {
		if (vpMatched != null) {
			Reporting_person person;
			for (int i = 0, max = vpMatched.size(); i < max; i++) {
				person = (Reporting_person) vpMatched.get(i);
				if (person.getFirst_name().compareToIgnoreCase(personName) == 0) {
					return person;
				}
			}
		}
		return null;
	}

	private List<Reporting_person> generatePersonListMatches(String searchWord,
			int maxMatches) {
		ArrayList matchList = new ArrayList(maxMatches);
		setVpFullList(projectService.getListOfVPs());
		
		
		// ensure the autocomplete search word is present
		if ((searchWord == null) || (searchWord.trim().length() == 0)) {
			return matchList;
		}

		SelectItem searchItem = new SelectItem("", searchWord);
		int insert = Collections.binarySearch(vpFullList, searchItem,PERSON_COMPARATOR);

		// less then zero if we have a partial match
		if (insert < 0) {
			insert = Math.abs(insert) - 1;
		} else {
			// If there are duplicates in a list, ensure we start from the first
			// one
			if (insert != vpFullList.size()
					&& PERSON_COMPARATOR.compare(searchItem, vpFullList.get(insert)) == 0) {
				while (insert > 0
						&& PERSON_COMPARATOR.compare(searchItem, vpFullList.get(insert - 1)) == 0) {
					insert = insert - 1;
				}
			}
		}

		for (int i = 0; i < maxMatches; i++) {
			// quit the match list creation if the index is larger than
			// max entries in the vpFullList if we have added maxMatches.
			if ((insert + i) >= vpFullList.size() || i >= maxMatches) {
				break;
			}
			matchList.add(vpFullList.get(insert + i));
		}

		// assign new matchList
		return matchList;
	}

	public List<Reporting_person> getVpFullList() {
		return vpFullList;
	}

	public void setVpFullList(List<Reporting_person> vpFullList) {
		this.vpFullList = vpFullList;
	}

	public List<Reporting_person> getVpMatched() {
		return vpMatched;
	}

	public void setVpMatched(List<Reporting_person> vpMatched) {
		this.vpMatched = vpMatched;
	}

	private static final Comparator PERSON_COMPARATOR = new Comparator() {
		public int compare(Object o1, Object o2) {
			String name =  ((Reporting_person)o1).getFirst_name();
			String selectItem = ((SelectItem) o2).getLabel();
			// compare ignoring case, give the user a more automated feel when
			// typing
			return name.compareToIgnoreCase(
					selectItem);
		}
	};

	
	public String projectClickEdit() {
		
		setSelectedProject(projectList.get(Integer.parseInt(selectedId)));
		
		if (!selectedProject.getCaProfileList().isEmpty()) {
			selectedCAIndex = 0;
			showCAInfo = true;
			setSelectedCA(selectedProject.getCaProfileList().get(selectedCAIndex));
		} else{
			selectedCAIndex = -1;
			showCAInfo = false;
			setSelectedCA(null);
		}
		
		
		return "editProjectPage";
	}

	public Project getSelectedProject() {
		return selectedProject;
	}

	public void setSelectedProject(Project selectedProject) {
		this.selectedProject = selectedProject;
	}
	
	/**
     * <p>Action event method which is triggered when a user clicks on the
     * upload file button.  Uploaded files are added to a list so that user have
     * the option to delete them programatically.  Any errors that occurs
     * during the file uploaded are added the messages output.</p>
     *
     * @param event jsf action event.
     */
    public void uploadFile(ActionEvent event) {
        InputFile inputFile = (InputFile) event.getSource();
        FileInfo fileInfo = inputFile.getFileInfo();
        if (fileInfo.getStatus() == FileInfo.SAVED) {
            // reference our newly updated file for display purposes and
            // added it to our history file list.
            currentFile = new InputFileData(fileInfo);

            synchronized (fileList) {
                fileList.add(currentFile);
            }

        }

    }

    /**
     * <p>This method is bound to the inputFile component and is executed
     * multiple times during the file upload process.  Every call allows
     * the user to finds out what percentage of the file has been uploaded.
     * This progress information can then be used with a progressBar component
     * for user feedback on the file upload progress. </p>
     *
     * @param event holds a InputFile object in its source which can be probed
     *              for the file upload percentage complete.
     */
    public void fileUploadProgress(EventObject event) {
        InputFile ifile = (InputFile) event.getSource();
        fileProgress = ifile.getFileInfo().getPercent();
    }

    /**
     * <p>Allows a user to remove a file from a list of uploaded files.  This
     * methods assumes that a request param "fileName" has been set to a valid
     * file name that the user wishes to remove or delete</p>
     *
     * @param event jsf action event
     */
    public void removeUploadedFile(ActionEvent event) {
        // Get the inventory item ID from the context.
        FacesContext context = FacesContext.getCurrentInstance();
        Map map = context.getExternalContext().getRequestParameterMap();
        String fileName = (String) map.get("fileName");

        synchronized (fileList) {
            InputFileData inputFileData;
            for (int i = 0; i < fileList.size(); i++) {
                inputFileData = (InputFileData)fileList.get(i);
                // remove our file
                if (inputFileData.getFileInfo().getFileName().equals(fileName)) {
                    fileList.remove(i);
                    break;
                }
            }
        }
    }

    public InputFileData getCurrentFile() {
        return currentFile;
    }

    public int getFileProgress() {
        return fileProgress;
    }

    public List getFileList() {
        return fileList;
    }

    public boolean isAutoUpload() {
        return autoUpload;
    }

    public void setAutoUpload(boolean autoUpload) {
        this.autoUpload = autoUpload;
    }
	


	public void saveProjectListener(ActionEvent e){
    	
    	//TODO: add save 
    	
    	
    }

	
	public void switchCAprofile(ValueChangeEvent  e){
    	
		String aString=e.getNewValue().toString();
    	setSelectedCA(projectService.getCAProfileFromListById(aString,selectedProject.getCaProfileList() ));
		
    }


	public int getSelectedCAIndex() {
		return selectedCAIndex;
	}

	public void setSelectedCAIndex(int selectedCAIndex) {
		this.selectedCAIndex = selectedCAIndex;
	}

	public CAProfile getSelectedCA() {
		return selectedCA;
	}

	public void setSelectedCA(CAProfile selectedCA) {
		this.selectedCA = selectedCA;
	}

	public boolean isShowCAInfo() {
		return showCAInfo;
	}

	public void setShowCAInfo(boolean showCAInfo) {
		this.showCAInfo = showCAInfo;
	}
    

    
}
